package com.my.app.tools.core.service.other;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.my.app.tools.core.service.AbstractAppConfigService;
import com.my.app.tools.core.service.common.AppConfigService;
import com.my.app.tools.pojo.vo.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * 生成数据业务
 *
 * @author guochaohui
 */
public class MakePeopleInfoService extends AbstractAppConfigService {

    private final Random random = new Random();

    private List<String> mobileBeginList;
    private List<String> peopleLastNameList;
    private List<String> peopleFemaleNameList;
    private List<String> peopleMaleNameList;
    private List<String> idCardBeginList;
    private List<BankTypeConfigVO> bankTypeList;

    @Override
    public void reloadAppConfig() {
        String mobileBegins = AppConfigService.readStringConfig("/app-config/make-people/mobile-begin");
        mobileBeginList = Splitter.on(",").trimResults().splitToList(mobileBegins);
        String peopleLastNames = AppConfigService.readStringConfig("/app-config/make-people/people-name/last-name");
        peopleLastNameList = Splitter.on(",").trimResults().splitToList(peopleLastNames);
        String peopleFemaleNames = AppConfigService.readStringConfig("/app-config/make-people/people-name/female-name");
        peopleFemaleNameList = Splitter.on(",").trimResults().splitToList(peopleFemaleNames);
        String peopleMaleNames = AppConfigService.readStringConfig("/app-config/make-people/people-name/male-name");
        peopleMaleNameList = Splitter.on(",").trimResults().splitToList(peopleMaleNames);
        String idCardBegin = AppConfigService.readStringConfig("/app-config/make-people/id-card-begin");
        idCardBeginList = Splitter.on(",").trimResults().splitToList(idCardBegin);

        List<String> bankCardShortNames = AppConfigService.readListConfig("/app-config/make-people/bank-card-list/info/short-name");
        List<String> bankCardChineseNames = AppConfigService.readListConfig("/app-config/make-people/bank-card-list/info/chinese-name");
        List<String> bankCardBegins = AppConfigService.readListConfig("/app-config/make-people/bank-card-list/info/begin");
        List<String> bankCardlengths = AppConfigService.readListConfig("/app-config/make-people/bank-card-list/info/length");
        bankTypeList = Lists.newArrayList();
        for (int i = 0; i < bankCardShortNames.size(); i++) {
            bankTypeList.add(
                    new BankTypeConfigVO(
                            bankCardShortNames.get(i)
                            , bankCardChineseNames.get(i)
                            , bankCardBegins.get(i)
                            , Integer.valueOf(bankCardlengths.get(i))
                    ));
        }
    }

    public List<String> queryBankTypes() {
        if (CollectionUtils.isEmpty(bankTypeList)) {
            return Lists.newArrayList();
        }
        List<String> list = Lists.newArrayList();
        for (int i = 0; i < bankTypeList.size(); i++) {
            list.add(bankTypeList.get(i).getChineseName());
        }
        return list;
    }

    /**
     * 生成随机个人信息
     *
     * @param param
     * @return
     */
    public List<PeopleInfoVO> generatePeopleInfo(MakePeopleInfoParamVO param) {
        List<PeopleInfoVO> list = Lists.newArrayList();
        for (int i = 0; i < param.getGenerateCount(); i++) {
            int gender = param.getGender().intValue() == -1 ? random.nextInt(2) : param.getGender();
            IdCardInfoVO idCardInfo = generateIdCardInfo(gender);
            BankCardInfoVO bankCardInfo = generateBankCardInfo(param.getBankCardType());
            PeopleInfoVO vo = new PeopleInfoVO();
            vo.setPeopleName(generatePeopleName(gender));
            vo.setPeopleGender(gender == 1 ? "男" : "女");
            vo.setPeopleIdCardNo(idCardInfo.getIdCardNo());
            vo.setPeopleAge(idCardInfo.getAge());
            vo.setPeopleBrithday(DateFormatUtils.format(idCardInfo.getBrithday(), "yyyy-MM-dd"));
            vo.setPeopleMobile(generateMobile());
            vo.setPeopleBankCard(bankCardInfo);
            list.add(vo);
        }
        return list;
    }

    /**
     * 生成随机银行卡信息
     *
     * @return
     */
    private BankCardInfoVO generateBankCardInfo(Integer bankCardType) {
        final int checkBankBinMaxCount = 1000;
        BankTypeConfigVO bankTypeConfig = (BankTypeConfigVO) getRandomObject(bankTypeList);
        int checkBankBinCount = 0;
        while (checkBankBinMaxCount > checkBankBinCount) {
            checkBankBinCount++;
            StringBuilder sb = new StringBuilder();
            sb.append(bankTypeConfig.getBeginCardNo());
            sb.append(RandomStringUtils.randomNumeric(6));
            sb.append(RandomStringUtils.randomNumeric(6));
            sb.append(RandomStringUtils.randomNumeric(6));
            String cardNo = StringUtils.left(sb.toString(), bankTypeConfig.getCardLength());
            if (!checkBankBin(cardNo)) {
                continue;
            }
            BankCardInfoVO bankCardInfoVO = new BankCardInfoVO();
            bankCardInfoVO.setCardNo(cardNo);
            bankCardInfoVO.setCnName(bankTypeConfig.getChineseName());
            bankCardInfoVO.setEnName(bankTypeConfig.getShortName());
            return bankCardInfoVO;
        }
        return null;
    }

    private boolean checkBankBin(String bankCardNo) {
        int checkSum = 0;
        for (int i = bankCardNo.length() - 1; i > 0; i--) {
            int b = Integer.valueOf(StringUtils.substring(bankCardNo, i - 1, i));
            if (i % 2 == 1) {
                checkSum += b * 2;
                if (b * 2 > 9) {
                    checkSum -= 9;
                }
            } else {
                checkSum += b;
            }
        }
        return checkSum % 10 == 0;
    }

    /**
     * 生成随机手机号
     *
     * @return
     */
    private String generateMobile() {
        StringBuilder sb = new StringBuilder();
        sb.append(getRandomObject(mobileBeginList));
        sb.append(RandomStringUtils.randomNumeric(4));
        sb.append(RandomStringUtils.randomNumeric(4));
        return sb.toString();
    }

    /**
     * 生成随机人名
     *
     * @param gender 0女、1男
     * @return
     */
    private String generatePeopleName(int gender) {
        List<String> otherNameList = gender == 1 ? peopleMaleNameList : peopleFemaleNameList;
        StringBuilder sb = new StringBuilder();
        sb.append(getRandomObject(peopleLastNameList));
        sb.append(getRandomObject(otherNameList));
        if (random.nextBoolean()) {
            sb.append(getRandomObject(otherNameList));
        }
        return sb.toString();
    }

    /**
     * 生成随机身份证件号
     *
     * @param gender 0女、1男
     * @param age    年龄，不传随机生成
     * @return
     */
    private IdCardInfoVO generateIdCardInfo(int gender, Integer age) {
        Date brithday = null;
        if (age == null) {
            brithday = generateAdultBrithday();
        } else {
            brithday = generateBrithday(age);
        }
        String areaCode = String.valueOf(getRandomObject(idCardBeginList));
        int iCode = random.nextInt(1000);
        if ((gender == 1 && iCode % 2 == 0) || (gender == 0 && iCode % 2 == 1)) {
            iCode++;
        }
        String code = StringUtils.leftPad(String.valueOf(iCode), 3, "0");

        StringBuilder sb = new StringBuilder();
        sb.append(areaCode);
        sb.append(DateFormatUtils.format(brithday, "yyyyMMdd"));
        sb.append(code);
        sb.append(generateIdCardTrailingNo(sb.toString()));

        String idCardNo = sb.toString();


        IdCardInfoVO idCardInfo = new IdCardInfoVO();
        idCardInfo.setIdCardNo(idCardNo);
        idCardInfo.setBrithday(brithday);
        idCardInfo.setGender(gender);
        idCardInfo.setAge(calcAge(brithday));
        return idCardInfo;
    }

    /**
     * 生成随机身份证件号
     *
     * @param gender 0女、1男
     * @return
     */
    private IdCardInfoVO generateIdCardInfo(int gender) {
        return generateIdCardInfo(gender, null);
    }

    /**
     * 根据生日实时计算年龄
     *
     * @param brithday
     * @return
     */
    private Integer calcAge(Date brithday) {
        Integer now = Integer.valueOf(DateFormatUtils.format(new Date(), "yyyyMMdd"));
        Integer brith = Integer.valueOf(DateFormatUtils.format(brithday, "yyyyMMdd"));
        return (now - brith) / 10000;
    }

    /**
     * 生成身份证号尾号
     *
     * @param idCardBegin17
     * @return
     */
    private String generateIdCardTrailingNo(String idCardBegin17) {
        idCardBegin17 = StringUtils.left(idCardBegin17, 17);
        List<String> cArray = Splitter.on(",").omitEmptyStrings().splitToList("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2");
        List<String> rArray = Splitter.on(",").omitEmptyStrings().splitToList("1,0,X,9,8,7,6,5,4,3,2");
        int result = 0;
        for (int i = 0; i < idCardBegin17.length(); i++) {
            int r1 = Integer.valueOf(cArray.get(i));
            int r2 = Integer.valueOf(StringUtils.substring(idCardBegin17, i, i + 1));
            result += r1 * r2;
        }
        return rArray.get(result % 11);
    }

    /**
     * 生成指定年龄的生日日期
     *
     * @return
     */
    private Date generateBrithday(int age) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR) - age;
        int month = random.nextInt(12);
        int date = 1 + random.nextInt(31);
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 生成随机成年人生日，当前日期20岁~60岁
     *
     * @return
     */
    private Date generateAdultBrithday() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR) - (20 + random.nextInt(41));
        int month = random.nextInt(12);
        int date = 1 + random.nextInt(31);
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DATE, date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 从list中随机取值
     *
     * @param list
     * @return
     */
    private Object getRandomObject(List<?> list) {
        return list.get(random.nextInt(list.size()));
    }

}
